'''
1. compute graph
2. linear model train
'''
import tensorflow as tf 

node1 = tf.constant(3.0, tf.float32)
node2 = tf.constant(4.0) # tf.float32 is default type
print(node1,node2) 

sess = tf.Session()
print(sess.run([node1,node2]))

node3 = tf.add(node1,node2)
print("node3: ", node3)
print("sess.run(node3): ", sess.run(node3))

a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b # equal tf.add(a, b)

print(sess.run(adder_node, {a:3, b:4.5}))
print(sess.run(adder_node, {a:[1,3], b: [2, 4]}))

add_and_triple = adder_node * 3
print(sess.run(add_and_triple, {a:3, b: 4.5}))

# use variables
w = tf.Variable([0.3], tf.float32)
b = tf.Variable([-0.3], tf.float32)
x = tf.placeholder(tf.float32)
linear_model = w*x + b

# need init variables before run model
init_variables = tf.global_variables_initializer()
sess.run(init_variables)

print(sess.run(linear_model, {x:[1,2,3,4]}))

# loss
y = tf.placeholder(tf.float32)
squared_deltas = tf.square(linear_model - y)
loss = tf.reduce_sum(squared_deltas)

print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]}))

# change variable
fix_w = tf.assign(w, [-1.0])
fix_b = tf.assign(b, [1.0])
print(sess.run([fix_w,fix_b]))
print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]}))

# train
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

sess.run(init_variables) # reset varibles
print(sess.run([w, b])) # before train

for i in range(1000):
    sess.run(train, {x:[1,2,3,4], y:[0,-1,-2,-3]})

print(sess.run([w, b])) # print train result

